#include "StdAfx.h"
#include "StdString.h"

CStdString::CStdString(void):m_pstr(m_szBuffer)
{
	memset(m_szBuffer,0x0,MAX_LOCAL_STRING_LEN);
	m_szBuffer[0] = '\0';
}

CStdString::CStdString(const TCHAR ch):m_pstr(m_szBuffer)
{
	memset(m_szBuffer,0x0,MAX_LOCAL_STRING_LEN);
	m_szBuffer[0] = ch;
	m_szBuffer[1] = '\0';
}

CStdString::CStdString(LPCTSTR lpsz,int nLen):m_pstr(m_szBuffer)
{
	Assign(lpsz,nLen);
}

CStdString::CStdString(const CStdString& src):m_pstr(m_szBuffer)
{
	Assign(src.m_szBuffer);
}

CStdString::~CStdString(void)
{
	if(m_pstr != m_szBuffer)
	{
		free(m_pstr);
		m_pstr = NULL;
	}
}

CStdString::operator LPCTSTR() const
{
	return m_pstr;
}

TCHAR CStdString::operator [](int nIndex) const
{
	return m_pstr[nIndex];
}

const CStdString& CStdString::operator = (const CStdString& src)
{
	Assign(src);
	return *this;
}

const CStdString& CStdString::operator = (LPCTSTR lpStr)
{
	Assign(lpStr);
	return *this;
}

CStdString CStdString::operator +(const CStdString &src)
{
	Append(src);
	return *this;
}

CStdString CStdString::operator +(LPCTSTR lpStr)
{
	Append(lpStr);
	return *this;
}

const CStdString& CStdString::operator +=(const CStdString& src)
{
	Append(src);
	return *this;
}

const CStdString& CStdString::operator +=(LPCTSTR lpStr)
{
	Append(lpStr);
	return *this;
}

const CStdString& CStdString::operator +=(const TCHAR ch)
{
	TCHAR str[] = {ch,'\0'};
	Append(str);
	return *this;
}

bool CStdString::operator == (LPCTSTR str) const 
{
	return (Compare(str) == 0);
}

bool CStdString::operator != (LPCTSTR str) const
{
	return (Compare(str) != 0);
}

bool CStdString::operator <= (LPCTSTR str) const
{
	return (Compare(str) <= 0);
}

bool CStdString::operator <  (LPCTSTR str) const
{ 
	return (Compare(str) <  0); 
}

bool CStdString::operator >= (LPCTSTR str) const 
{ 
	return (Compare(str) >= 0);
}

bool CStdString::operator >  (LPCTSTR str) const 
{ 
	return (Compare(str) >  0);
}

void CStdString::Assign(LPCTSTR pstr, int nLength)
{
	int cchMax = (nLength < 0 ? (int)_tcslen(pstr):nLength);
	if(cchMax < MAX_LOCAL_STRING_LEN)
	{
		if(m_pstr != m_szBuffer)
		{
			free(m_pstr);
			m_pstr = m_szBuffer;
		}
	}
	else if(cchMax > GetLength() || m_pstr == m_szBuffer)
	{
		if(m_pstr == m_szBuffer)
			m_pstr = NULL;
		m_pstr = static_cast<LPTSTR>(realloc(m_pstr,(cchMax+1)*sizeof(TCHAR)));
	}

	_tcsncpy(m_pstr,pstr,cchMax);
	m_pstr[cchMax] = '\0';
}

void CStdString::Append(LPCTSTR pstr)
{
	int nNewLength = GetLength() + (int) _tcslen(pstr);
	if(nNewLength >= MAX_LOCAL_STRING_LEN)
	{
		if(m_pstr == m_szBuffer)
		{
			m_pstr = static_cast<LPTSTR>(malloc((nNewLength + 1) * sizeof(TCHAR)));
			_tcscpy(m_pstr,m_szBuffer);
			_tcscat(m_pstr,pstr);
		}
		else
		{
			m_pstr = static_cast<LPTSTR>(realloc(m_pstr,(nNewLength + 1) * sizeof(TCHAR)));
			_tcscat(m_pstr,pstr);
		}
	}
	else
	{
		if(m_pstr != m_szBuffer)
		{
			free(m_pstr);
			m_pstr = m_szBuffer;
		}
		_tcscat(m_szBuffer,pstr);
	}
}

int CStdString::GetLength() const
{
	return (int) _tcslen(m_pstr);
}

CStdString CStdString::RES(UINT nRes)
{
	TCHAR szBuffer[256];
	/*int cchLen = ::LoadString(CPaintManagerUI::GetLanguageInstance(),nRes,szBuffer,lengthof(szBuffer) - 1);
	ASSERT(cchLen > 0);
	szBuffer[cchLen] = '\0';*/
	return szBuffer;
}

bool CStdString::IsEmpty() const
{
	return m_pstr[0] == '\0';
}

void CStdString::Empty()
{
	if(m_pstr != m_szBuffer)
		free(m_pstr);
	m_pstr = m_szBuffer;
	m_szBuffer[0] = '\0';
}

LPCTSTR CStdString::GetData()
{
	return m_pstr;
}

TCHAR CStdString::GetAt(int nIndex) const
{
	ASSERT(nIndex >= 0 && nIndex < GetLength());
	return m_pstr[nIndex];
}

void CStdString::SetAt(int nIndex, TCHAR ch)
{
	ASSERT(nIndex >= 0 && nIndex < GetLength());
	m_pstr[nIndex] = ch;
}

int CStdString::Compare(LPCTSTR pstr) const
{
	return _tcscmp(m_pstr,pstr);
}

int CStdString::CompareNoCase(LPCTSTR pstr) const
{
	return _tcsicmp(m_pstr,pstr);
}

void CStdString::MakeUpper()
{
	_tcsupr(m_pstr);
}

void CStdString::MakeLower()
{
	_tcslwr(m_pstr);
}

CStdString CStdString::Left(int nLength) const
{
	int nLen = 0;
	if(nLength > GetLength())
		nLen = GetLength();
	else
		nLen = nLength;
	return CStdString(m_pstr,nLen);
}

CStdString CStdString::Mid(int iPos, int nLength) const
{
	int nLen = 0;
	if(nLength < 0 || (iPos + nLength) > GetLength())
		nLen = GetLength() - iPos;
	else
		nLen = nLength;
	if(nLength <= 0)
		return CStdString();
	return CStdString(m_pstr + iPos,nLen);
}

CStdString CStdString::Right(int nLength) const
{
	int nLen = 0;
	int iPos = GetLength() - nLength;
	if(iPos < 0)
	{
		iPos = 0;
		nLen = GetLength();
	}
	else
	{
		nLen = nLength;
	}
	return CStdString(m_pstr + iPos,nLen);
}

int CStdString::Find(TCHAR ch, int iPos) const
{
	ASSERT(iPos >= 0 && iPos <= GetLength());
	if(iPos != 0 && (iPos < 0 || iPos >= GetLength()))
		return -1;
	LPCTSTR pstr = _tcschr(m_pstr + iPos,ch);
	if(pstr == NULL)
		return -1;
	return pstr - m_pstr;
}

int CStdString::Find(LPCTSTR pstrSub, int iPos) const
{
	ASSERT(iPos >= 0 && iPos <= GetLength());
	if(iPos != 0 && (iPos < 0 || iPos >= GetLength()))
		return -1;
	LPCTSTR pstr = _tcsstr(m_pstr + iPos,pstrSub);
	if(pstr == NULL)
		return -1;
	return pstr - m_pstr;
}

int CStdString::ReverseFind(TCHAR ch) const
{
	LPCTSTR pstr = _tcsrchr(m_pstr,ch);
	if(pstr == NULL)
		return -1;
	return pstr - m_pstr;
}

int CStdString::Replace(LPCTSTR pstrFrom, LPCTSTR pstrTo)
{
	CStdString strTemp;
	int nCount = 0;
	int iPos = Find(pstrFrom);
	if(iPos < 0)
		return 0;
	int cchFrom = (int)_tcslen(pstrFrom);
	int cchTo = (int)_tcslen(pstrTo);
	while (iPos >= 0)
	{
		strTemp = Left(iPos);
		strTemp += pstrTo;
		strTemp += Mid(iPos + cchFrom);
		Assign(strTemp);
		iPos = Find(pstrFrom,iPos + cchTo);
		nCount++;
	}
	return nCount;
}

void CStdString::ProcessResourceTokens()
{
	int iPos = Find('%');
	while(iPos >= 0)
	{
		if(iPos + 1 >= GetLength())
			break;
		if(GetAt(iPos + 1) == '{')
		{
			int iEndPos = iPos + 2;
			while(isdigit(GetAt(iEndPos)))
			{
				iEndPos++;
			}
			if(GetAt(iEndPos) == '}')
			{
				CStdString strTemp = CStdString::RES((UINT)_ttoi(m_pstr + iPos + 2));
				Replace(Mid(iPos,iEndPos - iPos + 1),strTemp);
			}
		}
		iPos = Find('%',iPos + 1);
	}
}

int CStdString::Format(LPCTSTR pstrFormat,...)
{
	CStdString sFormat = pstrFormat;
	sFormat.ProcessResourceTokens();
	TCHAR szBuffer[1025] = {0};
	va_list argList;
	va_start(argList,pstrFormat);
	int iRet = ::wvsprintf(szBuffer,sFormat,argList);
	va_end(argList);
	Assign(szBuffer);
	return iRet;
}